package com.son.hotel.controller;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.son.hotel.common.ErrorCode;
import com.son.hotel.common.Result;
import com.son.hotel.domain.AccommodationInfo;
import com.son.hotel.domain.Customers;
import com.son.hotel.domain.RoomType;
import com.son.hotel.domain.Rooms;
import com.son.hotel.execption.BusinessException;
import com.son.hotel.response.CustomerAndAccommodationResp;
import com.son.hotel.response.CustomerAndRoomInfoResp;
import com.son.hotel.response.RoomAccountResp;
import com.son.hotel.service.AccommodationInfoService;
import com.son.hotel.service.CustomersService;
import com.son.hotel.service.RoomTypeService;
import com.son.hotel.service.RoomsService;
import com.son.hotel.vo.CustomAndRoomInfo;

import com.son.hotel.vo.SearchInfo;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@RestController
@Slf4j
@RequestMapping("/menu")
public class AccommodationInfoController {

    @Autowired
    private CustomersService customersService;

    @Autowired
    private AccommodationInfoService accommodationInfoService;

    @Autowired
    private RoomTypeService roomTypeService;

    @Autowired
    private RoomsService roomsService;
    /**
     * 预定房间：顾客表(登记这个人的基本信息)、住宿表(登记住宿信息)、房间的类型表(数量减一)、房间表(修改状态)
     * @return
     */
    @Operation(summary = "预订房间-customer")
    @PostMapping("/book/room")
    public Result<Boolean> bookRoom(@RequestBody CustomAndRoomInfo customAndRoomInfo){
        log.info("住房登记信息:{}",customAndRoomInfo);
        //1.将信息添加到用户表中
        int res = customersService.addCustom(customAndRoomInfo);
        if (res <= 0){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"插入失败");
        }
        //2.添加住房信息
        accommodationInfoService.addAccommodationInfo(customAndRoomInfo);
        return Result.success("200",true);
    }

    /**
     * 获取预订信息
     * @param identity
     * @param typeId
     * @return
     */
    @Operation(summary = "住房和个人信息查询")
    @GetMapping("/living/info")
    public Result<CustomerAndAccommodationResp> getInfo(@RequestParam("identity") String identity
            ,@RequestParam("typeId") int typeId){
        log.info("identity:{}",identity);
        log.info("typeId:{}",typeId);
        QueryWrapper<Customers> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("identity",identity);
        //TODO 查询用户
        Customers customers = customersService.getOne(queryWrapper);
        log.info("customers:{}",customers);
        //TODO 查询房间的类型名称
        RoomType roomType = roomTypeService.getById(typeId);
        log.info("roomType:{}",roomType);
        String name = customers.getName();
        String phone = customers.getPhone();
        Integer customersId = customers.getId();
        //TODO 查询住房的信息
        QueryWrapper<AccommodationInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("customer_id",customersId);
        AccommodationInfo accommodationInfo = accommodationInfoService.getOne(queryWrapper1);
        log.info("accommodationInfo:{}",accommodationInfo);
        //装载数据
        CustomAndRoomInfo customAndRoomInfo = new CustomAndRoomInfo();
        customAndRoomInfo.setName(name);
        customAndRoomInfo.setPhone(phone);
        customAndRoomInfo.setIdentity(identity);
        customAndRoomInfo.setPrice(accommodationInfo.getCost());
        customAndRoomInfo.setStartTime(Convert.toStr(accommodationInfo.getInDate()));
        customAndRoomInfo.setEndTime(Convert.toStr(accommodationInfo.getOutDate()));

        CustomerAndAccommodationResp customerAndAccommodationResp = new CustomerAndAccommodationResp();
        customerAndAccommodationResp.setCustomAndRoomInfo(customAndRoomInfo);
        customerAndAccommodationResp.setRoomName(roomType.getName());
        customerAndAccommodationResp.setRoomId(accommodationInfo.getRoomId());
        customerAndAccommodationResp.setCustomerId(customersId);
        return Result.success("200",customerAndAccommodationResp);
    }


    /**
     * 列出客户和房间的信息(admin)
     * @return
     */
    @Operation(summary = "顾客管理-查询-admin")
    @GetMapping("/customer/list")
    public Result<List<CustomerAndRoomInfoResp>> listCustomerAndRoomInfo(){
        //查询顾客房间的信息
        List<AccommodationInfo> list = accommodationInfoService.list();

        List<CustomerAndRoomInfoResp> customerAndRoomList
                = accommodationInfoService.listCustomerAndRoomInfo(list);

        return Result.success("200",customerAndRoomList);
    }

    /**
     * 修改住房信息(PS:只修改用户的房间号)
     * @param customerAndRoomInfoResp
     * @return
     */
    @Operation(summary = "顾客管理-修改-admin")
    @Transactional
    @PostMapping("/customer/update")
    public Result<ErrorCode> updateCustomerAndRoomInfo(
            @RequestBody CustomerAndRoomInfoResp customerAndRoomInfoResp){
        log.info("customerAndRoomInfoResp:{}",customerAndRoomInfoResp);
        //计算住宿时长
        DateTime startTime = DateUtil.parse(customerAndRoomInfoResp.getStartTime(), "yyyy-MM-dd");
        DateTime endTime = DateUtil.parse(customerAndRoomInfoResp.getEndTime(), "yyyy-MM-dd");
        int duration = (int)DateUtil.between(startTime, endTime, DateUnit.DAY);
        //TODO 计算住宿费用（PS：只能先预定一天，之后修改计算出来的价格才正确）
        int price = customerAndRoomInfoResp.getCost();
        int cost = price * duration;
        //修改条件
        UpdateWrapper<AccommodationInfo> wrapper = new UpdateWrapper<>();
        wrapper
                .set("room_id",customerAndRoomInfoResp.getNewRoomId())
                .set("in_date",customerAndRoomInfoResp.getStartTime())
                .set("out_date",customerAndRoomInfoResp.getEndTime())
                .set("duration",duration)
                .set("cost",cost)
                .eq("customer_id",customerAndRoomInfoResp.getId());
        //TODO 修改用户的房间号
        boolean result = accommodationInfoService.update(wrapper);
        if (!result){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"修改错误");
        }
        //TODO 修改房间的状态
        Rooms oldRooms = roomsService.getById(customerAndRoomInfoResp.getOldRoomId());
        Rooms newRooms = roomsService.getById(customerAndRoomInfoResp.getNewRoomId());
        //将老房间的状态改成0
        roomsService.updateRoomStatus(oldRooms);
        //将新房间的状态改成1
        roomsService.updateRoomStatus(newRooms);

        //TODO 修改房间的数量
        //如果新老房间类型不一样则改数量
        if (!Objects.equals(oldRooms.getTypeId(), newRooms.getTypeId())){
            //将老房间的类型数量加1
            roomTypeService.updateRoomTypeInfoInc(oldRooms.getTypeId());
            //将新房间的类型属性减1
            roomTypeService.updateRoomTypeInfoDec(newRooms.getTypeId());
        }
        return Result.success("200",ErrorCode.SUCCESS);
    }

    /**
     * 删除顾客住房信息
     * @param id
     * @param roomId
     * @return
     */
    @Operation(summary = "顾客管理-修改-admin")
    @DeleteMapping("/customer/delete")
    public Result<ErrorCode> deleteCustomerAndRoomInfo(@RequestParam int id,@RequestParam int roomId){
//        QueryWrapper<AccommodationInfo> queryWrapper1 = new QueryWrapper<>();
//        queryWrapper1.eq("customer_id",id);
        //TODO 删除住房信息表中的数据
        //accommodationInfoService.remove(queryWrapper1);
        //TODO 删除用户表中的数据
        customersService.removeById(id);
        //TODO 修改房间表的状态
        Rooms rooms = roomsService.getById(roomId);
        roomsService.updateRoomStatus(rooms);
        //TODO 让房间类型表的数量加1
        Integer typeId = rooms.getTypeId();
        roomTypeService.updateRoomTypeInfoInc(typeId);

        return Result.success("200",ErrorCode.SUCCESS);
    }

    /**
     * 新增顾客住房信息
     * @param customerAndRoomInfoResp
     * @return
     */
    @Operation(summary = "顾客管理-新增-admin")
    @PostMapping("/customer/add")
    public Result<ErrorCode> addCustomerAndRoomInfo(
            @RequestBody CustomerAndRoomInfoResp customerAndRoomInfoResp){
        log.info("customerAndRoomInfoResp:{}",customerAndRoomInfoResp);
        //TODO 顾客表中插入一条信息
        customersService.addCustom(customerAndRoomInfoResp);
        //TODO 房间类型表中对应的数量减一
        Rooms newRooms = roomsService.getById(customerAndRoomInfoResp.getNewRoomId());
        log.info("newRooms:{}",newRooms);
        roomTypeService.updateRoomTypeInfoDec(newRooms.getTypeId());
        //TODO 房间表中更改状态
        //将新房间的状态改成1
        roomsService.updateRoomStatus(newRooms);
        //TODO 住房信息表中插入一条信息
        //先得获取用户的id
        Customers customer = customersService.getCustomerByIdentity(customerAndRoomInfoResp.getIdentity());
        Integer customerId = customer.getId();
        customerAndRoomInfoResp.setId(customerId);
        //向住宿信息表插入数据
        accommodationInfoService.addAccommodationInfo(customerAndRoomInfoResp);
        return Result.success("200",ErrorCode.SUCCESS);
    }

    /**
     * 搜索用户住房信息(admin)
     * @param searchInfo
     * @return
     */
    @Operation(summary = "顾客管理-搜索-admin")
    @PostMapping("/customerInfo/search")
    public Result<List<CustomerAndRoomInfoResp>> searchCustomerAndRoomInfo(@RequestBody SearchInfo searchInfo){
        //查询顾客房间的信息
        List<AccommodationInfo> list = accommodationInfoService.list();
        List<CustomerAndRoomInfoResp> customerAndRoomList
                = accommodationInfoService.listCustomerAndRoomInfo(list);
        for (CustomerAndRoomInfoResp customerAndRoomInfoResp : customerAndRoomList) {
            // 1. 使用 Hutool 解析时间字符串
            Date startDate = DateUtil.parse(customerAndRoomInfoResp.getStartTime());
            Date endDate = DateUtil.parse(customerAndRoomInfoResp.getEndTime());
            // 2. 格式化为 yyyy-MM-dd
            String startTime = DateUtil.format(startDate, "yyyy-MM-dd");
            String endTime = DateUtil.format(endDate, "yyyy-MM-dd");

            customerAndRoomInfoResp.setStartTime(startTime);
            customerAndRoomInfoResp.setEndTime(endTime);
        }
        log.info("customerAndRoomList:{}",customerAndRoomList);

        if (Objects.equals(searchInfo.getKey(), "房号")){
            String value = searchInfo.getValue();
            int roomId = Integer.parseInt(value);
            return Result.success("200",customerAndRoomList.stream().filter(s->s.getNewRoomId() == roomId).toList());
        }
        else if (Objects.equals(searchInfo.getKey(), "入住时间")){
            return Result.success("200",customerAndRoomList.stream().filter(s->s.getStartTime().contains(searchInfo.getValue())).toList());
        }
        else {
            return Result.success("200",customerAndRoomList.stream().filter(s->s.getEndTime().contains(searchInfo.getValue())).toList());
        }
    }

    @Operation(summary = "统计住房信息-admin")
    @GetMapping("/room/account")
    public Result<List<RoomAccountResp>> listRoomAccount(
            @RequestParam int year,
            @RequestParam int month){
        //调用Service层
        List<RoomAccountResp> roomAccountResp = accommodationInfoService.listRoomAccount(year, month);
        for (RoomAccountResp accountResp : roomAccountResp) {
            int typeId = accountResp.getTypeId();
            //使用typeId在rooms表查询有多少该类型有多少个房间
            QueryWrapper<Rooms> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("typeId",typeId);
            //该类型所有房间的数量
            long count = roomsService.count(queryWrapper);
            //该月这个类型入住的房间的数量
            int accountRespCount = accountResp.getCount();
            //入住率
            float percent = (float) accountRespCount / (count*30);
            //保留小数点后两位
            BigDecimal bd = new BigDecimal(percent).setScale(4, RoundingMode.HALF_UP);
            float roundedPercent = bd.floatValue();
            String percentage = String.format("%.2f%%", roundedPercent * 100);

            accountResp.setPercent(percentage);
        }
        log.info("统计信息:{}",roomAccountResp);
        return Result.success("200",roomAccountResp);
    }
}
